home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Snippets / Interapplication Communication / FinderOpenSelection 1.0.1 / FinderOpenSel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  29.1 KB  |  824 lines  |  [TEXT/MPS ]

  1. /* FinderOpenSel 1.1 */
  2. /* This sample shows how to use the Finder OpenSelection AppleEvent. */
  3. /* You can use this event to launch applications or files, or open Finder windows */
  4. /* Version 1.1 here also shows you how to launch an application remotely */
  5. /* Written  by C.K. Haun <TR> */
  6. /* Apple Developer Tech Support */
  7. /* April 1992, Cupertino, CA USA */
  8. /* Of course, Copyright 1991-1992, Apple Computer Inc. */
  9. #include <Types.h>
  10. #include <memory.h>
  11. #include <Packages.h>
  12. #include <Errors.h>
  13. #include <quickdraw.h>
  14. #include <fonts.h>
  15. #include <dialogs.h>
  16. #include <windows.h>
  17. #include <menus.h>
  18. #include <events.h>
  19. #include <OSEvents.h>
  20. #include <Desk.h>
  21. #include <diskinit.h>
  22. #include <OSUtils.h>
  23. #include <resources.h>
  24. #include <toolutils.h>
  25. #include <AppleEvents.h>
  26. #include <EPPC.h>
  27. #include <GestaltEqu.h>
  28. #include <PPCToolbox.h> 
  29. #include <Processes.h>
  30. #include <Balloons.h>
  31. #include <ALiases.h>
  32. #include <Processes.h>
  33. #include <StandardFile.h>
  34. #include <Folders.h>
  35. /* prototypes */
  36. void InitalizeApp(void);
  37. void DoDiskEvents(long dinfo);                              /* hi word is error code, lo word is drive number */
  38. void DrawMain(WindowPtr drawIt);
  39. Boolean DoSelected(long val);
  40. OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN, ProcessInfoRecPtr infoRecToFill);
  41. OSErr OpenSelection(short which);
  42. void InitAEStuff(void);
  43. void DoHighLevel(EventRecord *AERecord);
  44. void DoDaCall(MenuHandle themenu, long theit);
  45. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  46. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  47. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  48. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  49. void SampleHelpDialog(void);
  50. OSErr GetPathAndName(Str255 fullPath, Str255 appName);
  51. OSErr BrowseFerMe(void);
  52. pascal Boolean FinderFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo);
  53. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem);
  54. pascal Boolean idleProc(EventRecord *eventIn, long *sleep, RgnHandle *mouseRgn);
  55.  
  56. long trashDirID;
  57. short trashVRef;
  58. /* These are the new Dialog Manager calls described in Tech note #304 */
  59. /* ONLY used if System 7 or later, of course */
  60. pascal OSErr GetStdFilterProc(ModalFilterProcPtr *theProc) = 
  61. {
  62.     0x303C, 0x0203, 0xAA68
  63. };
  64.  
  65.  
  66.  
  67.  
  68. /* Indicates to the dialog manager which item is default.  Will then alias the return key */
  69. /* to this item, and also bold border it for you (yaaaaa!) */
  70. pascal OSErr SetDialogDefaultItem(DialogPtr theDialog, short newItem)
  71. {
  72.     0x303C, 0x0304, 0xAA68
  73. };
  74.  
  75.  
  76.  
  77.  
  78. /* Indicates which item should be aliased to escape or Command - . */
  79. pascal OSErr SetDialogCancelItem(DialogPtr theDialog, short newItem)
  80. {
  81.     0x303C, 0x0305, 0xAA68
  82. };
  83.  
  84.  
  85.  
  86.  
  87. /* Tells the dialog manager that there is an edit line in this dialog, and */
  88. /* it should track and change to an I-Beam cursor when over the edit line */
  89. pascal OSErr SetDialogTracksCursor(DialogPtr theDialog, Boolean tracks) = 
  90. {
  91.     0x303C, 0x0306, 0xAA68
  92. };
  93.  
  94.  
  95.  
  96.  
  97. /* one external */
  98. extern void _DataInit();                                    /* this is the C initialization code */
  99.  
  100. #define kWaitDialog 132
  101. #define kMBarID 128
  102. #define kAppleMenu 128
  103. #define kFileMenu 129
  104. #define kEditMenu 130
  105. #define kToolsMenu 131
  106. #define kResumeMask 1 /* bit of message field for resume vs. suspend */
  107. #define kSampHelp 129
  108. #define kAboutBox 128
  109. #define kHelpString 128
  110. #define kNewItem 1
  111. #define kOpenItem 2
  112. #define kCloseItem 3
  113. #define kSaveItem 4
  114. #define kSaveAsItem 5
  115. #define kFileBlank1 6
  116. #define kPageSetupItem 7
  117. #define kPrintItem 8
  118. #define kFileBlank2 9
  119. #define kQuitItem 10
  120. #define kBadSystem 130
  121. #define kOpenAppItem 1
  122. #define kOpenWindowItem 2
  123. #define kRemoteLaunchItem 3
  124. #define kTextType 'TEXT'
  125. #define kTextResID 128
  126. #define kMyWindowResID 128
  127. #define aeSelectionKeyword 'fsel'
  128. #define kAEOpenSelection 'sope'
  129. #define kFinderType 'FNDR'
  130. #define kSysCreator 'MACS'
  131. #define kPathDialog 131
  132. #define kEditLineItem 4
  133. #define kColon ':'
  134. enum  {
  135.     kGenStrings = 128, kPPCPrompt1 = 1, kPPCPrompt2
  136. };
  137.  
  138. struct AEinstalls {
  139.     AEEventClass theClass;
  140.     AEEventID theEvent;
  141.     EventHandlerProcPtr theProc;
  142. };
  143. typedef struct AEinstalls AEinstalls;
  144.  
  145. Handle gMymenu;                                             /* my menu bar handle */
  146. MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle;
  147. Boolean gQuit, gInBackground;
  148. EventRecord gERecord;
  149. AEDesc gTheAddress;
  150. WindowPtr myWindow = 0;
  151. ProcessSerialNumber gOurSN;
  152. short gHelpItem;
  153. LocationNameRec theLoc;
  154. PortInfoRec theRec;
  155. PPCPortRec myPortName;
  156. LocationNameRec myLoc;
  157. AEDesc myAddressDesc;
  158. TargetID theID;
  159. #pragma segment Main
  160. main()
  161. {
  162.     WindowPtr twindow;
  163.     
  164.     UnloadSeg((Ptr)_DataInit);                              /* throw out setup code */
  165.     InitalizeApp();
  166.     UnloadSeg((Ptr)InitalizeApp);                           /* get rid of my initialization code */
  167.     
  168.     do {
  169.         WaitNextEvent(everyEvent, &gERecord, 5, nil);
  170.         switch (gERecord.what) {
  171.             
  172.             case nullEvent:
  173.                 
  174.                 /* no nul processing in this sample */
  175.                 break;
  176.             case updateEvt:
  177.                 DrawMain((WindowPtr)gERecord.message);      /* draw whatever window needs an update */
  178.                 break;
  179.             case mouseDown:
  180.                 
  181.                 /* first see where the hit was */
  182.                 
  183.                 switch (FindWindow(gERecord.where, &twindow)) {
  184.                     
  185.                     case inDesk:                            /* if they hit in desk, then the process manager */
  186.                         break;                              /* will switch us out, we don't need to do anything */
  187.                     case inMenuBar:
  188.                         DoSelected(MenuSelect(gERecord.where));
  189.                         break;
  190.                         
  191.                     case inSysWindow:
  192.                         /* pass to the system */
  193.                         SystemClick(&gERecord, twindow);
  194.                         break;
  195.                         
  196.                     case inContent:
  197.                         /* Handle content and control clicks here */
  198.                         break;
  199.                         
  200.                     case inDrag:
  201.                         if (twindow == FrontWindow())
  202.                             DragWindow(twindow, gERecord.where, &qd.screenBits.bounds);
  203.                         break;
  204.                         
  205.                     case inGrow:
  206.                         /* Call GrowWindow here if you have a grow box */
  207.                         break;
  208.                         
  209.                     case inGoAway:
  210.                         /* Click in Close box */
  211.                         break;
  212.                         
  213.                 }
  214.             case mouseUp:
  215.                 /* don't care */
  216.                 break;
  217.                 
  218.                 /* same action for key or auto key */
  219.                 
  220.             case keyDown:
  221.             case autoKey:
  222.                 if (gERecord.modifiers & cmdKey)
  223.                     DoSelected(MenuKey(gERecord.message & charCodeMask));
  224.                 break;
  225.                 
  226.             case keyUp:
  227.                 /* don't care */
  228.                 break;
  229.                 
  230.             case diskEvt:
  231.                 /* I don't do anything special for disk events, this just passes them */
  232.                 /* to a function that checks for an error on the mount */
  233.                 DoDiskEvents(gERecord.message);
  234.                 break;
  235.                 
  236.             case activateEvt:
  237.                 if (gERecord.modifiers & activeFlag)
  238.                     DrawMain((WindowPtr)gERecord.message);
  239.                 break;
  240.                 
  241.             case networkEvt:
  242.                 /* don't care */
  243.                 break;
  244.                 
  245.             case driverEvt:
  246.                 /* don't care */
  247.                 break;
  248.                 
  249.             case app4Evt:
  250.                 switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  251.                     case suspendResumeMessage:              /* suspend/resume is also an activate/deactivate */
  252.                         gInBackground = (gERecord.message & kResumeMask) == 0;
  253.                         break;
  254.                 }
  255.                 break;
  256.                 
  257.                 /* This dispatches high level events (AppleEvents, for example) */
  258.                 /* to our dispatch routine.  This is NEW in the event loop for */
  259.                 /* System 7 */
  260.                 
  261.             case kHighLevelEvent:
  262.                 DoHighLevel(&gERecord);
  263.                 break;
  264.                 
  265.             default:
  266.                 break;
  267.                 
  268.         }
  269.     }
  270.             while (gQuit != true);
  271.     
  272. }
  273.  
  274. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  275. /* like to perform some action or just know when a DA is opened in your */
  276. /* layer.  Can be handy to track memory problems when a DA is opened */
  277. /* with an Option-open */
  278. void DoDaCall(MenuHandle themenu, long theit)
  279. {
  280.     long qq;
  281.     char DAname[255];
  282.     GetItem(themenu, theit, &DAname);
  283.     qq = OpenDeskAcc(DAname);
  284. }
  285.  
  286. /* end DoDaCall */
  287.  
  288. /* DoDiskEvents just checks the error code from the disk mount, */
  289. /* and puts up the 'Format' dialog (through DIBadMount) if need be */
  290. /* You can do much more here if you care about what disks are */
  291. /* in the drive */
  292. void DoDiskEvents(long dinfo)                               /* hi word is error code, lo word is drive number */
  293. {
  294.     short hival, loval, tommy;
  295.     Point fredpoint =  {
  296.         40, 40
  297.     };
  298.     hival = HiWord(dinfo);
  299.     loval = LoWord(dinfo);
  300.     if (hival != noErr)                                     /* something happened */ {
  301.         tommy = DIBadMount(fredpoint, dinfo);
  302.     }
  303. }
  304.  
  305. /* draws my window.  Pretty simple */
  306. void DrawMain(WindowPtr drawIt)
  307. {
  308.     Handle theText;
  309.     BeginUpdate(drawIt);
  310.     SetPort(drawIt);
  311.     EraseRect(&drawIt->portRect);
  312.     theText = GetResource(kTextType, kTextResID);
  313.     if (theText) {
  314.         Rect textRect;
  315.         HLock(theText);
  316.         HUnlock(theText);
  317.         textRect = drawIt->portRect;
  318.         InsetRect(&textRect, 5, 5);
  319.         TextBox(*theText, GetHandleSize(theText), &textRect, 0);
  320.         ReleaseResource(theText);
  321.     }
  322.     EndUpdate(drawIt);
  323. }
  324.  
  325. /* my menu action taker.  It returns a Boolean which I usually ignore, but it */
  326. /* mught be handy someday */
  327. Boolean DoSelected(long val)
  328. {
  329.     short loval, hival;
  330.     Boolean returnVal = false;
  331.     loval = LoWord(val);
  332.     hival = HiWord(val);
  333.     
  334.     switch (hival) {                                        /* switch off the menu number selected */
  335.         
  336.         case kAppleMenu:                                    /* Apple menu */
  337.             if (loval != 1) {                               /* if this was not About, it's a DA */
  338.                 DoDaCall(gAppleMenuHandle, loval);
  339.             } else {
  340.                 Alert(kAboutBox, nil);                      /* do about box */
  341.             }
  342.             returnVal = true;
  343.             break;
  344.             
  345.         case kFileMenu:                                     /* File menu */
  346.             switch (loval) {
  347.                 
  348.                 case kQuitItem:
  349.                     gQuit = true;                           /* only  item */
  350.                     returnVal = true;
  351.                     break;
  352.                     
  353.                 default:
  354.                     break;
  355.             }
  356.             break;
  357.             
  358.         case kEditMenu:
  359.             /* edit menu junk */
  360.             /* don't care */
  361.             break;
  362.             
  363.         case kToolsMenu:
  364.             /* add all your test stuff here */
  365.             OpenSelection(loval);
  366.             break;
  367.             
  368.         case kHMHelpMenuID:                                 /* Defined in Balloons.h */
  369.             /* I only care about this item.  If anything else is returned here, I don't know what */
  370.             /* it is, so I leave it alone.  Remember, the Help Manager chapter says that */
  371.             /* Apple reserves the right to add and change things in the Help menu */
  372.             if (loval == gHelpItem)
  373.                 SampleHelpDialog();
  374.             break;
  375.             
  376.     }
  377.     HiliteMenu(0);
  378.     return(returnVal);
  379. }
  380.  
  381. /* InitAEStuff installs my appleevent handlers */
  382. void InitAEStuff(void)
  383. {
  384.     static AEinstalls HandlersToInstall[] =  {
  385.         {
  386.             kCoreEventClass, kAEOpenApplication, AEOpenHandler
  387.         },  {
  388.             kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler
  389.         },  {
  390.             kCoreEventClass, kAEQuitApplication, AEQuitHandler
  391.         },  {
  392.             kCoreEventClass, kAEPrintDocuments, AEPrintHandler
  393.         }, 
  394.         /* The above are the four required AppleEvents. */
  395.         
  396.     };
  397.     
  398.     OSErr aevtErr = noErr;
  399.     long aLong = 0;
  400.     Boolean gHasAppleEvents = false;
  401.     
  402.     /* Check this machine for AppleEvents.  If they are not here (ie not 7.0)
  403.     *   then we exit */
  404.     
  405.     gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
  406.     
  407.     /* The following series of calls installs all our AppleEvent Handlers.
  408.     *   These handlers are added to the application event handler list that 
  409.     *   the AppleEvent manager maintains.  So, whenever an AppleEvent happens
  410.     *   and we call AEProcessEvent, the AppleEvent manager will check our
  411.     *   list of handlers and dispatch to it if there is one.
  412.     */
  413.     
  414.     if (gHasAppleEvents) {
  415.         register qq;
  416.         for (qq = 0; qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls))); qq++) {
  417.             
  418.             aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
  419.                                             HandlersToInstall[qq].theProc, 0, false);
  420.             if (aevtErr) {
  421.                 ExitToShell();                              /* just fail, baby */
  422.             }
  423.         }
  424.     } else {
  425.         ExitToShell();
  426.     }
  427. }
  428.  
  429. /* end InitAEStuff */
  430. /* I'm not doing error handling in this sample for clarities sake, you should. Hah, */
  431. /* easy for me to say, huh? */
  432. void DoHighLevel(EventRecord *AERecord)
  433. {
  434.     
  435.     AEProcessAppleEvent(AERecord);
  436.     
  437. }
  438.  
  439. /* end DoHighLevel */
  440.  
  441. /* This is the standard Open Application event.  */
  442. pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  443. {
  444. #pragma unused (messagein,reply,refIn)
  445.     /* we of course don't do anything here in this simple app */
  446.     /* except open our window */
  447.     
  448.     myWindow = GetNewWindow(kMyWindowResID, nil, (WindowPtr)-1);
  449.     return(noErr);
  450. }
  451.  
  452. /* end AEOpenHandler */
  453.  
  454. /* Open Doc, opens our documents.  Remember, this can happen at application start AND */
  455. /* anytime else.  If your app is up and running and the user goes to the desktop, hilites one */
  456. /* of your files, and double-clicks or selects Open from the finder File menu this event */
  457. /* handler will get called. Which means you don't do any initialization of globals here, or */
  458. /* anything else except open then doc.  */
  459. /* SO-- Do NOT assume that you are at app start time in this */
  460. /* routine, or bad things will surely happen to you. */
  461.  
  462. pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  463. {
  464. #pragma unused (messagein,refIn,reply)
  465.     /* we of course don't do anything here */
  466.     
  467.     return(errAEEventNotHandled);                           /* we have no docs, so no odoc events should come to us */
  468. }
  469.  
  470. pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  471. {                                                           /* no printing handler in yet, so we'll ignore this */
  472.     /* the operation is functionally identical to the ODOC event, with the additon */
  473.     /* of calling your print routine.  */
  474. #pragma unused (messagein,refIn,reply)
  475.     
  476.     /* we of course don't do anything here */
  477.     return(errAEEventNotHandled);                           /* we have no docs, so no pdoc events should come to us */
  478. }
  479.  
  480. /* Standard Quit event handler, to handle a Quit event from the Finder, for example.  */
  481. /* ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have a happy life.  */
  482. pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  483. {
  484. #pragma unused (messagein,refIn,reply)
  485.     
  486.     /* prepQuit sets the Stop flag for us.  It does _NOT_ quit, you */
  487.     /* should NEVER quit from an AppleEvent handler.  Calling */
  488.     /* ExitToShell here would blow things up */
  489.     gQuit = true;
  490.     return(noErr);
  491. }
  492.  
  493. /* This is my sample help dialog.  Does not do anything, expand as you need */
  494. void SampleHelpDialog(void)
  495. {
  496.     DialogPtr tdial = GetNewDialog(kSampHelp, nil, (WindowPtr)-1);
  497.     short itemhit = 0;
  498.     while (itemhit != 1) {
  499.         ModalDialog((ModalFilterProcPtr)nil, &itemhit);
  500.     }
  501.     DisposDialog(tdial);
  502. }
  503.  
  504. /* OpenSelection perpares and sends the Finder OpenSelection event */
  505. /* Three choices currently.  If which is 1, then we do an OpenSelection on the file itself. */
  506. /* if which is 2, then we tell the finder to open the directory window containing the file  */
  507. /* if it's 3, then we ask for a remote name and launch remotely */
  508.  
  509. OSErr OpenSelection(short which)
  510. {
  511.     AppleEvent aeEvent, aeReply;
  512.     AEDesc aeDirDesc, listElem;
  513.     OSErr interactErr = noErr;
  514.     FSSpec dirSpec, procSpec;
  515.     AEDesc fileList;
  516.     StandardFileReply myReply;
  517.     OSErr myErr;
  518.     ProcessSerialNumber process;
  519.     AliasHandle DirAlias, FileAlias;
  520.     FSSpecPtr theFileToOpen = nil;
  521.     ProcessInfoRec infoRec;
  522.     Str31 processName;
  523.     Str255 fullPath;
  524.     Str255 appName;
  525.     
  526.     if (which != kRemoteLaunchItem)
  527.         StandardGetFile(nil, -1, nil, &myReply);
  528.     else
  529.         myReply.sfGood = true;                              /* set this since I want to be silent this time */
  530.     if (myReply.sfGood) {
  531.         theFileToOpen = &myReply.sfFile;
  532.         infoRec.processInfoLength = sizeof(ProcessInfoRec);
  533.         infoRec.processName = &processName;
  534.         infoRec.processAppSpec = &procSpec;
  535.         
  536.         /* Browse for the Finder you wish to communicate with */
  537.         
  538.         if (which != kRemoteLaunchItem) {
  539.             /* if less than kRemoteLaunchItem, then we are working locally, find the finder on this machine */
  540.             
  541.             myErr = FindAProcess(kFinderType, kSysCreator, &process, &infoRec);
  542.             if (myErr == noErr)
  543.                 myErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
  544.             
  545.         } else {
  546.             
  547.             /* Get a remote finder  */
  548.             myErr = BrowseFerMe();
  549.         }
  550.         if (myErr == noErr) {
  551.             
  552.             /* Create the FinderEvent */
  553.             myErr = AECreateAppleEvent(kFinderType, kAEOpenSelection, &myAddressDesc, kAutoGenerateReturnID, kAnyTransactionID,
  554.                                        &aeEvent);
  555.             /* If you want to keep talking to this machine, you can keep this  */
  556.             /* address desc around */
  557.             AEDisposeDesc(&myAddressDesc);
  558.             
  559.             if (myErr == noErr) {
  560.                 /* Now we build all the bits of an OpenSelection event. */
  561.                 /* Basically, we need to create an alias for the item to open, and an alias to the parent */
  562.                 /* folder (directory) of that item. */
  563.                 /* We can also pass a list of files if we want.  */
  564.                 /* You'll notice that for opening a finder window, the file and directory alias both point at the */
  565.                 /* folder itself */
  566.                 /* make a spec for the parent folder */
  567.                 
  568.                 if (which != kRemoteLaunchItem) {
  569.                     FSMakeFSSpec(theFileToOpen->vRefNum, theFileToOpen->parID, nil, &dirSpec);
  570.                     NewAlias(nil, &dirSpec, &DirAlias);
  571.                 }
  572.                 /* Create alias for file */
  573.                 /* if you are opening a window, then you make the file alias the same as the dir alias */
  574.                 switch (which) {
  575.                     
  576.                     case kOpenAppItem:
  577.                         NewAlias(nil, theFileToOpen, &FileAlias);
  578.                         break;
  579.                         
  580.                     case kOpenWindowItem:
  581.                         NewAlias(nil, &dirSpec, &FileAlias);
  582.                         
  583.                         /* I want to set the Finder as the front process after the event  */
  584.                         /* is sent (if I can) so you can see what happened.  Rememeber, app switches */
  585.                         /* don't happen until _after_ (or during) the next WaitNextEvent call */
  586.                         
  587.                         interactErr = AEInteractWithUser(kAEDefaultTimeout, nil, (IdleProcPtr)idleProc);
  588.                         if (interactErr == noErr)
  589.                             SetFrontProcess(&process);
  590.                         break;
  591.                         
  592.                     case kRemoteLaunchItem:
  593.                         myErr = GetPathAndName(fullPath, appName);
  594.                         if (myErr == noErr) {
  595.                             /* NewAliasMinimalFromFullPath (geez what a lot of typing) creates an alias that does NOT */
  596.                             /* have a file ID, just builds based on what it has, the path.  So we don't need to */
  597.                             /* connect to another machine or file server to make this alias, which is why this thing works. */
  598.                             
  599.                             NewAliasMinimalFromFullPath(appName[0], (Ptr)&appName[1], "", "", &FileAlias);
  600.                             NewAliasMinimalFromFullPath(fullPath[0], (Ptr)&fullPath[1], "", "", &DirAlias);
  601.                         }
  602.                         break;
  603.                 }
  604.                 /* Create the file  list */
  605.                 if (myErr == noErr) {
  606.                     myErr = AECreateList(nil, 0, false, &fileList);
  607.                     
  608.                     /*  create the folder  descriptor */
  609.                     HLock((Handle)DirAlias);
  610.                     AECreateDesc(typeAlias, (Ptr)*DirAlias, GetHandleSize((Handle)DirAlias), &aeDirDesc);
  611.                     HUnlock((Handle)DirAlias);
  612.                     if ((myErr = AEPutParamDesc(&aeEvent, keyDirectObject, &aeDirDesc)) == noErr) {
  613.                         /* done with the desc, kill it */
  614.                         AEDisposeDesc(&aeDirDesc);
  615.                         /*  create the file descriptor and add to aliasList */
  616.                         HLock((Handle)FileAlias);
  617.                         AECreateDesc(typeAlias, (Ptr)*FileAlias, GetHandleSize((Handle)FileAlias), &listElem);
  618.                         HLock((Handle)FileAlias);
  619.                         myErr = AEPutDesc(&fileList, 0, &listElem);
  620.                     }
  621.                     if (myErr == noErr) {
  622.                         
  623.                         AEDisposeDesc(&listElem);
  624.                         
  625.                         /* Add the file alias list to the event */
  626.                         myErr = AEPutParamDesc(&aeEvent, aeSelectionKeyword, &fileList);
  627.                         AEDisposeDesc(&fileList);
  628.                         
  629.                         if (myErr == noErr)
  630.                             myErr = AESend(&aeEvent, &aeReply, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
  631.                                            kAENormalPriority, kAEDefaultTimeout, nil, nil);
  632.                     }
  633.                 }
  634.                 AEDisposeDesc(&aeEvent);
  635.             }
  636.         }
  637.     }
  638.     if ((Handle)DirAlias)
  639.         DisposHandle((Handle)DirAlias);
  640.     if ((Handle)FileAlias)
  641.         DisposHandle((Handle)FileAlias);
  642.     return(myErr);
  643. }
  644.  
  645.  
  646.  
  647. /* This runs through the process list looking for the indicated application */
  648. OSErr FindAProcess(OSType typeToFind, OSType creatorToFind, ProcessSerialNumberPtr processSN, ProcessInfoRecPtr infoRecToFill)
  649. {
  650.     ProcessSerialNumber tempPSN;
  651.     OSErr myErr = noErr;
  652.     tempPSN.lowLongOfPSN = kNoProcess;
  653.     processSN->lowLongOfPSN = kNoProcess;
  654.     processSN->highLongOfPSN = kNoProcess;
  655.     do {
  656.         myErr = GetNextProcess(processSN);
  657.         if (myErr == noErr)
  658.             GetProcessInformation(processSN, infoRecToFill);
  659.     }
  660.             while ((infoRecToFill->processSignature != creatorToFind || infoRecToFill->processType != typeToFind) ||
  661.                    myErr != noErr);
  662.     
  663.     return(myErr);
  664. }
  665.  
  666. /*  BrowseFerMe calls the PPC browser and creates an AEAddressDesc out of the Browser */
  667. /* info if the user (you) doesn't cancel */
  668.  
  669. OSErr BrowseFerMe(void)
  670. {
  671.     OSErr myErr = noErr;
  672.     Str255 tWext;
  673.     
  674.     Str255 t2Wext;
  675.     GetIndString(tWext, kGenStrings, kPPCPrompt1);
  676.     GetIndString(t2Wext, kGenStrings, kPPCPrompt2);
  677.     myErr = PPCBrowser(tWext, &t2Wext, false, &theLoc, &theRec, (PPCFilterProcPtr)FinderFilter, nil);
  678.     if (myErr == noErr) {
  679.         theID.name = theRec.name;
  680.         theID.location = theLoc;
  681.         myErr = AECreateDesc(typeTargetID, (Ptr)&theID, sizeof(theID), &myAddressDesc);
  682.     }
  683.     return(myErr);
  684. }
  685.  
  686. /* Show only FInders */
  687. pascal Boolean FinderFilter(LocationNamePtr locationName, PortInfoPtr thePortInfo)
  688. {
  689. #pragma unused (locationName)
  690.     OSType type;
  691.     
  692.     if (thePortInfo->name.portKindSelector == ppcByString) {
  693.         BlockMove(thePortInfo->name.u.portTypeStr + 1, (Ptr)&type, 4);
  694.         /* The BlockMove is so that we don't get an address error
  695.         ** on a 68000-based machine due to referencing a long at
  696.         ** an odd-address. */
  697.         if (type == kSysCreator)
  698.             return(true);
  699.     }
  700.     return(false);
  701. }
  702.  
  703. OSErr GetPathAndName(Str255 fullPath, Str255 appName)
  704. {
  705.     DialogPtr tdial = GetNewDialog(kPathDialog, nil, (WindowPtr)-1);
  706.     short hitItem = 0;
  707.     Str255 tempString;
  708.     short where;
  709.     ModalFilterProcPtr filterIt = nil;
  710.     
  711.     OSErr retVal = userCanceledErr;
  712.     SetDialogDefaultItem(tdial, ok);
  713.     SetDialogCancelItem(tdial, cancel);
  714.     SetDialogTracksCursor(tdial, true);
  715.     GetStdFilterProc(&filterIt);
  716.     ShowWindow(tdial);
  717.     DrawDialog(tdial);
  718.     do {
  719.         ModalDialog((ModalFilterProcPtr)filterIt, &hitItem);
  720.     }
  721.             while (hitItem != ok && hitItem != cancel);
  722.     if (hitItem == ok) {
  723.         GetIText((Handle)SnatchHandle(tdial, kEditLineItem), tempString);
  724.         /* now parse backwards to find the last colon, which is seperating the file name from the path */
  725.         where = tempString[0];
  726.         while (tempString[where] != kColon && where > 0)
  727.             where--;
  728.         if (where > 0) {
  729.             BlockMove((Ptr)&tempString[0], (Ptr)&appName[0], tempString[0] + 1);
  730.             BlockMove((Ptr)&tempString[0], (Ptr)&fullPath[0], where + 1);       /* include the colon */
  731.             fullPath[0] = where;
  732.             retVal = noErr;
  733.         }
  734.     }
  735.     DisposDialog(tdial);
  736.     
  737.     return(retVal);
  738. }
  739.  
  740. ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem)
  741. {
  742.     short itemtype;
  743.     Rect itemrect;
  744.     Handle thandle;
  745.     
  746.     GetDItem(thebox, theGetItem, &itemtype, &thandle, &itemrect);
  747.     return((ControlHandle)thandle);
  748. }
  749.  
  750. /* end SnatchHandle */
  751.  
  752. pascal Boolean idleProc(EventRecord *eventIn, long *sleep, RgnHandle *mouseRgn)
  753. {
  754.     switch (eventIn->what) {
  755.         case nullEvent:
  756.             /* no nul processing in this sample */
  757.             *sleep = 0;
  758.             mouseRgn = nil;
  759.             break;
  760.         case updateEvt:
  761.         case activateEvt:
  762.             DrawMain((WindowPtr)eventIn->message);          /* draw whatever window needs an update */
  763.             break;
  764.         case app4Evt:
  765.             switch ((gERecord.message >> 24) & 0x0FF) {     /* high byte of message */
  766.                 case suspendResumeMessage:                  /* suspend/resume is also an activate/deactivate */
  767.                     gInBackground = (gERecord.message & kResumeMask) == 0;
  768.                     break;
  769.             }
  770.             break;
  771.             
  772.     }
  773.     return(false);                                          /* I'll wait forever */
  774. }
  775.  
  776.  
  777. #pragma segment Initialize
  778. void InitalizeApp(void)
  779. {
  780.     MenuHandle helpHandle;
  781.     StringHandle helpString;
  782.     short count;
  783.     long vers;
  784.     MaxApplZone();
  785.     InitGraf((Ptr)&qd.thePort);
  786.     InitFonts();
  787.     InitWindows();
  788.     InitMenus();
  789.     TEInit();
  790.     InitDialogs(nil);
  791.     InitCursor();
  792.     /* Check system version */
  793.     Gestalt(gestaltSystemVersion, &vers);
  794.     vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */
  795.     if (vers < 7) {
  796.         StopAlert(kBadSystem, nil);
  797.         ExitToShell();
  798.     }
  799.     InitAEStuff();
  800.     /* set up my menu junk */
  801.     gMymenu = GetNewMBar(kMBarID);
  802.     SetMenuBar(gMymenu);
  803.     gAppleMenuHandle = GetMHandle(kAppleMenu);
  804.     gFileMenuHandle = GetMHandle(kFileMenu);
  805.     gEditMenuHandle = GetMHandle(kEditMenu);
  806.     gToolMenuHandle = GetMHandle(kToolsMenu);
  807.     AddResMenu(gAppleMenuHandle, 'DRVR');
  808.     /* now install my Help menu item in the Help Manager's menu */
  809.     HMGetHelpMenuHandle(&helpHandle);                       /* Get the Hlpe menu handle */
  810.     count = CountMItems(helpHandle);                        /* How many items are there? */
  811.     helpString = GetString(kHelpString);                    /* get my help string */
  812.     DetachResource(helpString);                             /* detach it */
  813.     HNoPurge(helpString);
  814.     MoveHHi((Handle)helpString);
  815.     HLock((Handle)helpString);
  816.     InsMenuItem(helpHandle, (Ptr)*helpString, count + 1);       /* insert my item in the Help menu */
  817.     gHelpItem = CountMItems(helpHandle);                    /* The number of the item */
  818.     
  819.     DrawMenuBar();
  820.     GetCurrentProcess(&gOurSN);                             /* Get our process serial number for later use, if needed */
  821. }
  822.